package com.xunce.xcworkservice.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xunce.xcworkservice.Enums.Enums;
import com.xunce.xcworkservice.dao.AccountDepartmentMapper;
import com.xunce.xcworkservice.dao.AccountMapper;
import com.xunce.xcworkservice.dao.AccountTokenMapper;
import com.xunce.xcworkservice.dao.AccountVerifyMapper;
import com.xunce.xcworkservice.dto.LoginDto;
import com.xunce.xcworkservice.entity.*;
import com.xunce.xcworkservice.exception.CustomException;
import com.xunce.xcworkservice.jwt.TokenGenerator;
import com.xunce.xcworkservice.service.*;
import com.xunce.xcworkservice.utils.PasswordUtil;
import com.xunce.xcworkservice.vo.IPageVo;
import com.xunce.xcworkservice.vo.UserInfoVo;
import com.xunce.xcworkservice.vo.UserSimpleVo;
import io.micrometer.common.util.StringUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author yanlong.guo
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> implements AccountService {


    private final AccountMapper accountMapper;

    private final AccountTokenMapper accountTokenMapper;

    private final AccountRolesService accountRolesService;

    private final RolesService rolesService;

    private final StationTitleService stationTitleService;

    private final DepartmentService departmentService;

    private final AccountDepartmentMapper accountDepartmentMapper;

    private final AccountVerifyMapper accountVerifyMapper;


    @Override
    public UserInfoVo login(LoginDto loginDto) throws CustomException {
        Account account = getUserByLogName(loginDto.getLoginName());
        if (account == null){
            throw new CustomException("登录失败:无效或非法的账号", 5002);
        }
        String loginPwd = PasswordUtil.encryptByMD5(loginDto.getPassword());
        if (!loginPwd.equals(account.getLoginPwd())){
            throw new CustomException("登录失败:密码不正确", 5003);
        }
        if (!account.getState().equals(Enums.AccountState.ENABLED.getValue())){
            throw new CustomException("登录失败:当前账号已禁用", 5004);
        }
        //生成token
        String token = TokenGenerator.generateValue(account.getAccountId().toString());
        LocalDateTime currentDateTime = LocalDateTime.now();
        // 获取当前时间的时间戳
        Instant currentInstant = currentDateTime.atZone(ZoneId.systemDefault()).toInstant();
        // 设置token过期时间
        Instant newInstant = currentInstant.plusSeconds(TokenGenerator.EXPIRE);
        // 将新的时间戳转换回 LocalDateTime
        LocalDateTime expireDateTime = LocalDateTime.ofInstant(newInstant, ZoneId.systemDefault());
        AccountToken accountToken = new AccountToken();
        accountToken.setUserId(account.getAccountId());
        accountToken.setName(account.getLoginName());
        accountToken.setToken(token);
        accountToken.setExpireTime(expireDateTime);
        accountToken.setToken(token);
        accountTokenMapper.insert(accountToken);
        UserInfoVo userInfoVo = new UserInfoVo();
        BeanUtils.copyProperties(account, userInfoVo);
        userInfoVo.setToken(token);
        List<UserInfoVo> userInfoVoList = new ArrayList<>();
        userInfoVoList.add(userInfoVo);
        batchSetAccountFillInfo(userInfoVoList);
        return userInfoVo;


    }

    @Override
    public void logOut() {
        //获取当前用户
        Subject subject = SecurityUtils.getSubject();
        UserInfoVo user = (UserInfoVo) subject.getPrincipal();
        accountTokenMapper.delete(new QueryWrapper<AccountToken>().lambda().eq(AccountToken::getToken, user.getToken()));
    }

    @Override
    public Account getUserByLogName(String logName){
        QueryWrapper<Account> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(Account::getLoginName, logName);

        return accountMapper.selectOne(wrapper);
    }

    @Override
    public IPageVo<UserInfoVo> selectPageByMap(Map<String, Object> params) {

        String name = (String) params.getOrDefault("name", "");
        String departmentIdentity = (String) params.getOrDefault("departmentIdentity", "");
        String need = (String) params.getOrDefault("need", "");
        LambdaQueryWrapper<Account> accountQueryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(name)){
            accountQueryWrapper.and(qw -> qw.like(Account::getAccountName, name).or().like(Account::getEnName, name));
        }
        if (StringUtils.isNotBlank(departmentIdentity)){
            accountQueryWrapper.eq(Account::getDepartmentIdentity, Integer.valueOf(departmentIdentity));
        }
        if (StringUtils.isNotBlank(need)){
            accountQueryWrapper.eq(Account::getNeed, Integer.valueOf(need));
        }
        long pageNo = Long.parseLong((String) params.getOrDefault("pageNo", 0));
        long pageSize = Long.parseLong((String) params.getOrDefault("pageSize", 50));
        Page<Account> page = new Page<>(pageNo, pageSize);
        List<Account> accounts;
        if (pageNo == 0){
            accounts = list(accountQueryWrapper);
        } else  {
            accounts = list(page, accountQueryWrapper);
        }
        List<UserInfoVo> userInfoVos = accounts.stream()
                .map(AccountServiceImpl::convertToUserVo)
                .toList();
        batchSetAccountFillInfo(userInfoVos);
        return IPageVo.result(userInfoVos, page.getCurrent(), page.getSize(), pageNo == 0 ? accounts.size() : page.getTotal());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(Account account) {

        if (account.getAccountId() != null){
            //更新指定字段
            UpdateWrapper<Account> wrappers = new UpdateWrapper<>();
            wrappers.lambda()
                    .eq(Account::getAccountId, account.getAccountId())
                    .set(Account::getAccountName, account.getAccountName())
                    .set(Account::getEnName, account.getEnName())
                    .set(Account::getSex, account.getSex())
                    .set(Account::getAddress, account.getAddress())
                    .set(Account::getStationTitleId, account.getStationTitleId())
                    .set(Account::getDepartmentIdentity, account.getDepartmentIdentity());
            update(wrappers);

        } else {
            //新增
            account.setNeed(Enums.AccountNeed.NEED.getValue());
            account.setLoginName(account.getEmail());
            account.setLoginPwd(PasswordUtil.encryptByMD5("123456"));
            account.setPhone(StringUtils.isNotBlank(account.getPhone()) ? account.getPhone() : "");
            save(account);
        }
        //更新角色
        accountRolesService.updateAccountRole(account.getAccountId(), account.getRoleIds());
        //更新部门
        departmentService.updateAccountDepartment(account.getAccountId(), account.getDepartmentIds());
    }

    @Override
    public void batchSetAccountFillInfo(List<UserInfoVo> userInfoVoList) {
        if (userInfoVoList == null || userInfoVoList.size() == 0){
            return;
        }
        List<AccountRoles> accountRolesList;
        if (userInfoVoList.size() > 100){
            accountRolesList = accountRolesService.list();
        }else {
            List<Integer> accountIds = userInfoVoList.stream().map(UserInfoVo::getAccountId).collect(Collectors.toList());
            QueryWrapper<AccountRoles> wrapper = Wrappers.query();
            wrapper.lambda().in(AccountRoles::getAccountId, accountIds);
            accountRolesList = accountRolesService.list(wrapper);
        }

        Map<Integer, List<Integer>> accountIdRolesMap = accountRolesList.stream()
                .collect(Collectors.groupingBy(AccountRoles::getAccountId,
                        Collectors.mapping(AccountRoles::getRoleId, Collectors.toList())));
        //所有角色
        List<Roles> rolesList = rolesService.list();
        Map<Integer, String> rolesMap = rolesList.stream()
                .collect(Collectors.toMap(Roles::getRoleId, Roles::getName));

        //所有职位
        List<StationTitle> stationTitles = stationTitleService.list();
        Map<Integer, String> stationMap = stationTitles.stream().collect(Collectors.toMap(StationTitle::getStationTitleId, StationTitle::getName));

        //所有员工映射部门
        List<AccountDepartment> accountDepartments = accountDepartmentMapper.selectList(null);
        Map<Integer, List<Integer>> accountDepartmentMap = accountDepartments.stream().collect(Collectors.groupingBy(AccountDepartment::getAccountId, Collectors.mapping(AccountDepartment::getDepartmentId, Collectors.toList())));

        //所有部门
        Map<Integer, Department> departmentMap = departmentService.getDepartmentMap();

        for (UserInfoVo userInfoVo : userInfoVoList){
            List<Integer> accountRoleIds = accountIdRolesMap.getOrDefault(userInfoVo.getAccountId(), null);
            if (accountRoleIds == null) {
                continue;
            }
            String roleName = "";
            for (Integer roleId : accountRoleIds){
                if (StringUtils.isNotBlank(roleName)) {
                    roleName += "|";
                }
                roleName += rolesMap.get(roleId);
            }
            userInfoVo.setRoleName(roleName);
            userInfoVo.setRoleIds(accountRoleIds);
            userInfoVo.setStationTitle(stationMap.getOrDefault(userInfoVo.getAccountId(), ""));
            //部门处理
            List<Integer> accountDepartIds = accountDepartmentMap.getOrDefault(userInfoVo.getAccountId(), null);
            if (accountDepartIds == null) {
                continue;
            }
            String departName = "";
            for (Integer departId : accountDepartIds){
                if (StringUtils.isNotBlank(departName)) {
                    departName += "|";
                }
                departName += departmentMap.get(departId).getNameAll();
            }
            userInfoVo.setDepartmentName(departName);
            userInfoVo.setDepartmentIds(accountDepartIds);
        }

    }

    @Override
    public List<UserSimpleVo> getTagAccount(String tag) {
        QueryWrapper<Account> accountQueryWrapper = null;
        if (StringUtils.isNotBlank(tag)){
            String[] tagArr = tag.split(",");
            accountQueryWrapper = new QueryWrapper<>();
           for (String tagItem : tagArr){
               accountQueryWrapper.or(wrapper -> wrapper.apply("FIND_IN_SET({0}, tag)", tagItem));
           }
        }
        List<Account> accountList = list(accountQueryWrapper);
        List<UserSimpleVo> UserSimpleVos = accountList.stream()
                .map(AccountServiceImpl::convertToUserSimpleVo)
                .toList();
        return UserSimpleVos;
    }

    // account转换为vo类型
    private static UserInfoVo convertToUserVo(Account account) {
        UserInfoVo userInfoVo = new UserInfoVo();
        BeanUtils.copyProperties(account, userInfoVo);
        return userInfoVo;
    }

    private static UserSimpleVo convertToUserSimpleVo(Account account) {
        UserSimpleVo userInfoVo = new UserSimpleVo();
        BeanUtils.copyProperties(account, userInfoVo);
        return userInfoVo;
    }
}
